package activator;

import java.util.Enumeration;

import library.service.LibraryService;
import listener.Listener;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.log.LogEntry;
import org.osgi.service.log.LogReaderService;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;

public class LibraryLogReaderActivator implements BundleActivator,
		ServiceTrackerCustomizer {

	// --- Members -------------------------------------------------------------
	private BundleContext bundleContext;
	private ServiceTracker logReaderTracker;
	private Listener listener;

	// service instances (for which logReaderTracker will listen)
	private LogReaderService logReaderService;
	private LibraryService libraryService;

	// constants
	private static final int MESSAGES_COUNT = 10;

	// --- Implementation BundleActivator interface ----------------------------

	public void start(BundleContext bundleContext) throws Exception {
		this.bundleContext = bundleContext;

		// initialize tracker for LogReaderService and LibraryService
		logReaderTracker = new ServiceTracker(bundleContext, createFilter(),
				this);
		logReaderTracker.open();

		if (logReaderService != null) { // tracker has tracked a
										// logReaderService
			// 1. print current logs
			printLogs();

			// 2. instantiate a LogListener
			listener = new Listener();

			// 3. add log listener to logReaderService
			logReaderService.addLogListener(listener);

			return;
		}
		throw new Exception("No LogReader Service!");
	}

	public void stop(BundleContext context) throws Exception {
		// 1 remove LogListener which has been added to LogReaderService
		logReaderService.removeLogListener(listener);

		// 2. close LogReaderTracker
		logReaderTracker.close();

		// 3. collect garbage
		listener = null;
		logReaderService = null;

	}

	// --- Implementation ServiceTrackerCustomizer interface -------------------

	public Object addingService(ServiceReference reference) {
		Object service = bundleContext.getService(reference);

		// instantiate the LogReaderService or the LibraryService reference
		// according to the type of tracked Service from LogReaderTracker

		if (service instanceof LogReaderService) {
			logReaderService = (LogReaderService) service;
			return service;
		} else if (service instanceof LibraryService) {
			libraryService = (LibraryService) service;
			return service;
		}
		return null;
	}

	public void modifiedService(ServiceReference reference, Object service) {

	}

	public void removedService(ServiceReference reference, Object service) {
		// set to NULL the service's reference according to service's type
		if (service instanceof LogReaderService) {
			logReaderService = null;
		} else if (service instanceof LibraryService) {
			libraryService = null;
		}
	}

	// --- Methods -------------------------------------------------------------
	public void printLogs() {
		Enumeration enums = logReaderService.getLog();

		// print the first MESSAGES_COUNT(or less if has no more) logs
		for (int i = MESSAGES_COUNT; enums.hasMoreElements() && i > 0; i--) {
			LogEntry logEntry = (LogEntry) enums.nextElement();

			printLogInConsole(logEntry.getBundle().getBundleId(),
					logEntry.getLevel(), logEntry.getMessage());
		}
	}

	public static void printLogInConsole(long bundleId, int level,
			String message) {

		System.out.println("bundleId= " + bundleId + ", level= " + level
				+ ", msg= " + message);
	}

	private Filter createFilter() throws InvalidSyntaxException {

		String stringFilter = "(" + Constants.OBJECTCLASS + "="
				+ LogReaderService.class.getName() + ")";
		stringFilter = "(|" + stringFilter + "(" + Constants.OBJECTCLASS + "="
				+ LibraryService.class.getName() + "))";

		return bundleContext.createFilter(stringFilter);
	}
}
